﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace iseeqq
{
    class QQProc
    {
        //    private IntPtr intptr;

        //用户名-密码
        private string username;
        private string password;

        //QQ托盘的位置
        public TrayInfo QQTray;


        private QQProc(string username, string password)
        {
            this.username = username;
            this.password = password;

        }


        private const string lpClassName = "TXGuiFoundation";
        private const string lpWindowName = "QQ";
        public static QQProc startPro(string path, string username, string password)
        {
            QQProc qq = new QQProc(username, password);

            var tray = qq.KillSIFExit();
            if (tray != null) //
            {
                Console.WriteLine("该QQ号已登录……");
                return qq;
            }
            else
            {
                Process proc = Process.Start(path);
                Console.WriteLine("程序启动pid： " + proc.Id);
                IntPtr intptr = waitForQQLoad();
                //IntPtr lpdwProcessId;
                //Win32API.GetWindowThreadProcessId(intptr, ref lpdwProcessId);
                //Console.WriteLine("登录窗口库进程号： " + lpdwProcessId);

                //StringBuilder s = new StringBuilder();
                //Win32API.GetWindowText(intptr, s, s.Capacity);
                //Console.WriteLine("获取窗口名称："+s.ToString());

                qq.login(intptr);
                return qq;
            }

        }

        public void login(IntPtr intptr)
        {
            //string tencentFile = QQValue.tencentFile;
            //Console.WriteLine("QQ用户保存地址" + tencentFile);
            //System.IO.Directory.Delete(tencentFile, true);

            //获取QQ坐标
            Win32API.RECT rc = new Win32API.RECT();
            Win32API.GetWindowRect(intptr, ref rc);
            int width = rc.Right - rc.Left; //窗口的宽度
            int height = rc.Bottom - rc.Top; //窗口的高度
            int x = rc.Left + 220;
            int y = rc.Top + 280;

            Console.WriteLine("窗口坐标: " + x + "\t" + y);
            Thread.Sleep(200);
            Win32API.SetCursorPos(x, y);
            Win32API.mouse_event(Win32API.MOUSEEVENTF_LEFTDOWN | Win32API.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
            InputText();

            //处理QQ托盘操作
            QQTray = watiForQQTary();
        }

        private void InputText()
        {
            Thread.Sleep(500);
            SendKeys.SendWait(this.username);
            Thread.Sleep(500);
            Win32API.keybd_event(Keys.Tab, 0, 0, 0);
            SendKeys.SendWait(this.password);
            Thread.Sleep(500);
            Win32API.keybd_event(Keys.Enter, 0, 0, 0);
        }

        /// <summary>
        /// 如果存在登录窗口，则杀死，重新打开
        /// </summary>
        private TrayInfo KillSIFExit()
        {
            IntPtr intptr = Win32API.FindWindow(lpClassName, lpWindowName);
            if (intptr != IntPtr.Zero)
            {
                intptr = Win32API.FindWindowEx(intptr, IntPtr.Zero, null, "QQEdit");
                if (intptr != IntPtr.Zero)
                {
                    Win32API.PostMessage(intptr, Win32API.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
                }
            }


            List<TrayInfo> taryList = WindowTools.GetTrayList();
            foreach (var item in taryList)
            {
                if (item.Title.Contains(username))
                {
                    return item;
                }
            }
            return null;
        }

        private static IntPtr waitForQQLoad()
        {
            IntPtr intptr, editptr;
            while (true)
            {
                intptr = Win32API.FindWindow(lpClassName, lpWindowName);
                if (intptr != IntPtr.Zero)
                {
                    editptr = Win32API.FindWindowEx(intptr, IntPtr.Zero, null, "QQEdit");
                    if (editptr != IntPtr.Zero)
                    {
                        Console.WriteLine();
                        return intptr;
                    }
                }
                else
                {
                    Console.Write("…");
                    Thread.Sleep(200);
                }

            }


        }

        private TrayInfo watiForQQTary()
        {
            int i = 0;
            while (true)
            {

                if (i > 10)//连续50次检测失败，退出
                {
                    Console.WriteLine("运行错误，请安任意键退出");
                    Console.ReadKey();
                    Environment.Exit(0);
                }
                else
                {
                    i++;
                    List<TrayInfo> taryList = WindowTools.GetTrayList();
                    foreach (var item in taryList)
                    {
                        if (item.Title.Contains(username))
                        {
                            return item;
                        }
                    }
                }

                Thread.Sleep(500);
            }

        }

        private bool isStop = true;

        internal void listening()
        {
            registHookKey();
            while (isStop)
            {
                TrayInfo qqTray = watiForQQTary();
                if (!qqTray.Tip.Contains(username))
                {
                    Console.Write("\r");
                    IntPtr winPtr =   popupMessage(qqTray); //弹出窗体的句柄
                    QQChatWindow qq = parseChatContext(winPtr);

                    if (qq != null)
                    {
                        Console.WriteLine(qq);
                        for (int i = 0; i < qq.context.Count; i++)
                        {
                            Console.WriteLine(qq.context[i]);
                        }
                    }
                    //关闭窗口
                    Win32API.PostMessage(winPtr, Win32API.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                }
                else
                {
                    Console.Write("\r 等待QQ消息");
                }
                Thread.Sleep(1000);
            }
        }

        private void registHookKey()
        {
            Win32API.HookProc lpfn = new Win32API.HookProc(Hook);
            IntPtr hInstance = Win32API.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
            Win32API.SetWindowsHookEx(Win32API.WH_KEYBOARD_LL, lpfn, hInstance, 0);
        }
        //钩子
        int idHook = 0;
        private int Hook(int nCode, IntPtr wParam, IntPtr lParam)
        {
            //键盘按下
            if (wParam.ToInt32() == Win32API.WM_KEYDOWN)
            {
                Win32API.HookMsg m = (Win32API.HookMsg)Marshal.PtrToStructure(lParam, typeof(Win32API.HookMsg));
                if (m.vkCode == (int)Keys.Escape)
                {
                    isStop = false;
                }
            }
            return Win32API.CallNextHookEx(idHook, nCode, wParam, lParam);
        }


        private bool firstInit = true;

        /// <summary>
        /// 弹出消息窗口
        /// </summary>
        /// <param name="QQTray"></param>
        public IntPtr popupMessage(TrayInfo QQTray)
        {
            Win32API.SetCursorPos(QQTray.Tect.Left + 5, QQTray.Tect.Top + 10);
            Win32API.mouse_event(Win32API.MOUSEEVENTF_LEFTDOWN | Win32API.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
            IntPtr result = IntPtr.Zero;
            string title = null;
            while (true)
            {
                result = Win32API.GetForegroundWindow();
                title = WindowTools.getWindowText(result);

                if (title != "")
                {
                    if (firstInit) // 第一次程序初始化，检查窗口是否“使用多彩气泡，”
                    {
                        QqWindowHelper.checkTextStype(result);
                        firstInit = false;
                    }

                    return result;
                }
                Thread.Sleep(500);
            }
        }


        const String groupRegExp = "(.*)\\((.+)\\)\\s+([0-9]{1,2}:[0-9]{2}:[0-9]{2})";
        const String personRegExp = "(.*)\\s+([0-9]{1,2}:[0-9]{2}:[0-9]{2})";
        private QQChatWindow parseChatContext(IntPtr intp)
        {
            QQChatWindow qqchat = new QQChatWindow();
            qqchat.intpr = intp;
            // title
            {
                qqchat.title = WindowTools.getWindowText(intp);
            }

            if (qqchat.title == "腾讯网")
            {
                qqchat = null;
                return qqchat;
            }

            //type
            {
                qqchat.type = QqWindowHelper.getChatType(intp);
            }

            // context;
            {
                string[] line = QqWindowHelper.getChatContext(intp).get_accValue(0).Split(new string[] { "\r" }, StringSplitOptions.None);
                List<ChatInfo> cinfoList = new List<ChatInfo>();
                ChatInfo cinfo = new ChatInfo();

                for (int i = 0; i < line.Length; i++)
                {
                    string str = line[i];

                    if (str.Trim() == "")
                    {
                        continue;
                    }
                    if (qqchat.type == 0) // 私聊
                    {
                        Match mat = Regex.Match(line[i], personRegExp);
                        if (mat.Success)
                        {
                            cinfoList.Add(cinfo);
                            cinfo = new ChatInfo();
                            cinfo.nick = mat.Groups[1].Value;
                            //  cinfo.account = mat.Groups[2].Value;
                            cinfo.date = mat.Groups[2].Value;
                        }
                        else
                        {
                            cinfo.context = cinfo.context + line[i] + "\n";
                        }
                    }
                    else // 群 组 
                    {
                        if (str.Contains("加入本群。"))
                            continue;
                        Match mat = Regex.Match(line[i], groupRegExp);
                        if (mat.Success)
                        {
                            cinfoList.Add(cinfo);
                            cinfo = new ChatInfo();
                            cinfo.nick = mat.Groups[1].Value;
                            cinfo.account = mat.Groups[2].Value;
                            cinfo.date = mat.Groups[3].Value;
                        }
                        else
                        {
                            cinfo.context = cinfo.context + line[i] + "\n";
                        }
                    }
                }
                cinfoList.Add(cinfo);
                if (cinfoList[0].context == null || cinfoList[0].context.Trim() == "")
                {
                    cinfoList.RemoveAt(0);
                }
                qqchat.context = cinfoList;

            }
            return qqchat;
        }

        struct ChatInfo
        {
            public string nick;
            public string account;
            public string date;
            public string context;


            public override string ToString()
            {
                return "[昵称]" + nick + "[账号]" + account + "[时间]" + date + "[内容]" + context;
            }

        }

        class QQChatWindow
        {
            /// <summary>
            /// 窗口句柄
            /// </summary>
            public IntPtr intpr;
            /// <summary>
            /// 窗口标题
            /// </summary>
            public string title;
            /// <summary>
            /// 窗口类型 0 个人 1 群 2 讨论组
            /// </summary>
            public int type;
            /// <summary>
            /// 窗口内容
            /// </summary>
            public List<ChatInfo> context;

            public override string ToString()
            {
                string typeName = "";
                switch (type)
                {
                    case 0:
                        typeName = "个人";
                        break;
                    case 1:
                        typeName = "群";
                        break;
                    case 2:
                        typeName = "讨论组";
                        break;
                    default:
                        typeName = "未知";
                        break;
                }
                return typeName + "@" + intpr + "[title]" + title;
            }

        }
    }
}
